# _*_coding:utf-8_*_

from ATS.instrumentDriver.IVGeneralFunc import IVGeneralFunc_B2900A as IVFunc
from ATS.util import mathlib as MathLib
from ATS.datamanager.DataManager import DataManager
from ATS.instrumentDriver import InstCom as inst
import copy

APD_SMU = "SMU2"

# error code
VP_VBR_MEAS_FAIL = -1001

Stop_for_Sweep = -200
at_Ibr = -1e-6


def APD_TEST_FIMV_D(source, src_range, meas_seq, meas_range, compliance, common, spec, post):
    """
    source = {"SMU1":([0<0=lin,1=myLog, 2=list>,0=start,500=stop],0=FI)}
    src_range = {"SMU1": ("Best Fixed", 500=max(source),0=FI)}
    meas_seq = {"SMU1":(2,["V","I"])}
    meas_range = {"SMU1":("Auto", 20, 1)}
    compliance = {"SMU1": (20,1)}
    common={"NPLC":1,"delay_time":0.1,"swp_pts":501}
    spec={"If":0.001,"Ibr":0.001, "Vr":20}
    """
    use_SMU = source.keys()[0]
    if APD_SMU and len(source.keys()) == 1:
        k = use_SMU
        update_k(source, k, APD_SMU)
        update_k(src_range, k, APD_SMU)
        update_k(meas_seq, k, APD_SMU)
        update_k(meas_range, k, APD_SMU)
        update_k(compliance, k, APD_SMU)
        use_SMU = APD_SMU
    for k in src_range:
        src_range[k] = list(src_range[k])
        rng_mode = key_convert("rng_mode", src_range[k][0])
        src_range[k][0] = rng_mode

    step = {}
    bias = {}
    open = {}
    remote_sense = {}
    meas_pro = {}
    common_ext = {"is_postdata": 0, "is_returndata": 1, "gs_flag": 1, "avg_num": 1, "sample_pts": 1,
                  "time_stamp": 0, "stop_comp": 0, "hold_time": 0, "step_pts": 1}

    # setup digital function as "digital IO"
    inst.write(use_SMU, ":sour:dig:ext13:func dio")

    sweep = copy.deepcopy(source)
    inst.write(use_SMU, ":sour:dig:ext13:pol neg")  # set to dark
    for k in meas_range:
        meas_range[k] = list(meas_range[k])
        rng_mode = key_convert("rng_mode", meas_range[k][0])
        meas_range[k][0] = rng_mode
    common_ext.update(common)
    IVFunc.setup(sweep, step, bias, open, meas_range, src_range, compliance, remote_sense,
                 meas_seq, meas_pro, common_ext)
    result = IVFunc.srcmeas(sweep, step, bias, open, meas_range, src_range, compliance,
                            remote_sense, meas_seq, meas_pro, common_ext)
    # print result
    V_list = result[use_SMU]["V"]
    I_list = result[use_SMU]["I"]
    if post.get("Vf"):
        If_pos = MathLib.FINDLIN(I_list, spec["If"], 0)
        Vf = MathLib.AT(V_list, If_pos)
        __postdata("Vf", [Vf])
    if post.get("Vbr"):
        Ibr_pos = MathLib.FINDLIN(I_list, spec["Ibr"], 0)
        Vbr = MathLib.AT(V_list, Ibr_pos)
        __postdata("Vbr", [Vbr])
    if post.get("Id"):
        Vr_pos = MathLib.FINDLIN(V_list, spec["Vr"], 0)
        Id = MathLib.AT(I_list, Vr_pos)
        __postdata("Id", [Id])
    __postdata("V", V_list)
    __postdata("I", I_list)

    is_manual = DataManager().getgdata("Manual_Run")
    # print is_manual
    if is_manual:  # do reset if manual run
        IVFunc.commonsetup(is_rst={use_SMU: 1})


def APD_TEST(is_d, is_p, source, src_range, meas_seq, meas_range, compliance, common, spec,
             meas_range_p, compliance_p, common_p, spec_p, post, post_p):
    """
    ########## output
    Only darkness = V, I, Vf, Vbr, Id
    Only photonic = V, I_p
    # 2014-06-10 Removed All = V, I, I_p, I_p_p, Vf, Vbr, Id, Ip1, Ip2, M
    # 2014-08-18 Removed All = V, I, I_p, I_p_p, Vf, Vbr, Id, Ip1, Ip2_M1, Ip2_M2, M1, M2
    All = V, I, I_p, I_p_p, Vf, Vbr, Id, Il0, Il1, Il2, M1, M2
    ########## source setting
    source = {"SMU1":([0,0=start,500=stop],1)}
    source_range = {"SMU1": ("Best Fixed", 500=max(source),1)}
    meas_seq = {"SMU1":(2,["V","I"])}

    ########## Measure setting and parameter for darkness
    meas_range = {"SMU1":("Limited  Auto", 0.0001, 0)}
    compliance = {"SMU1": (0.001,0)}
    common={"NPLC":1,"delay_time":0.1,"swp_pts":501}
    spec={"If":0.001,"Ibr":0.001, "Vr":20}

    ########### Measure setting and parameter for photonic
    meas_range_p = {"SMU1":("Limited  Auto", 0.0001, 0)}
    compliance_p = {"SMU1": (0.001,0)}
    common_p={"NPLC":1,"delay_time":0.1,"swp_pts":501}
    # 2014-06-10 Removed spec_p={"Vr1":20,"Vr2":40}
    # 2014-08-18 Removed spec_p={"Vr1":20,"Value":40}
    # spec_p={"Vr0":20,"Vr1":40, "Vx": 10}
    """
    global I_p_list, I_list, V_list, Vbr
    use_SMU = source.keys()[0]
    if APD_SMU and len(source.keys()) == 1:
        k = use_SMU
        update_k(source, k, APD_SMU)
        update_k(src_range, k, APD_SMU)
        update_k(meas_seq, k, APD_SMU)
        update_k(meas_range, k, APD_SMU)
        update_k(compliance, k, APD_SMU)
        update_k(meas_range_p, k, APD_SMU)
        update_k(compliance_p, k, APD_SMU)
        use_SMU = APD_SMU

    for k in src_range:
        src_range[k] = list(src_range[k])
        rng_mode = key_convert("rng_mode", src_range[k][0])
        src_range[k][0] = rng_mode

    step = {}
    bias = {}
    open = {}
    remote_sense = {}
    meas_pro = {}
    common_ext = {"is_postdata": 0, "is_returndata": 1, "gs_flag": 1, "avg_num": 1, "sample_pts": 1,
                  "time_stamp": 0, "stop_comp": 0, "hold_time": 0, "step_pts": 1}

    # setup digital function as "digital IO"
    inst.write(use_SMU, ":sour:dig:ext13:func dio")

    if is_d:  # no photomic
        sweep = copy.deepcopy(source)
        inst.write(use_SMU, ":sour:dig:ext13:pol neg")
        for k in meas_range:
            meas_range[k] = list(meas_range[k])
            rng_mode = key_convert("rng_mode", meas_range[k][0])
            meas_range[k][0] = rng_mode
        common_ext.update(common)
        IVFunc.setup(sweep, step, bias, open, meas_range, src_range, compliance, remote_sense,
                     meas_seq, meas_pro, common_ext)
        result = IVFunc.srcmeas(sweep, step, bias, open, meas_range, src_range, compliance,
                                remote_sense, meas_seq, meas_pro, common_ext)
        # print result
        V_list = result[use_SMU]["V"]
        I_list = result[use_SMU]["I"]
        if post.get("Vf"):
            If_pos = MathLib.FINDLIN(I_list, spec["If"], 0)
            Vf = MathLib.AT(V_list, If_pos)
            __postdata("Vf", [Vf])

        Ibr_pos = MathLib.FINDLIN(I_list, spec["Ibr"], 0)
        Vbr = MathLib.AT(V_list, Ibr_pos)
        if post.get("Vbr"):
            __postdata("Vbr", [Vbr])
        if post.get("Id"):
            Vr_pos = MathLib.FINDLIN(V_list, spec["Vr"], 0)
            Id = MathLib.AT(I_list, Vr_pos)
            __postdata("Id", [Id])
        __postdata("V", V_list)
        __postdata("I", I_list)

    if is_p:
        sweep = copy.deepcopy(source)
        inst.write(use_SMU, ":sour:dig:ext13:pol pos")
        for k in meas_range_p:
            meas_range_p[k] = list(meas_range_p[k])
            rng_mode = key_convert("rng_mode", meas_range_p[k][0])
            meas_range_p[k][0] = rng_mode
        common_ext.update(common_p)
        IVFunc.setup(sweep, step, bias, open, meas_range_p, src_range, compliance_p,
                     remote_sense, meas_seq, meas_pro, common_ext)
        result = IVFunc.srcmeas(sweep, step, bias, open, meas_range, src_range, compliance,
                                remote_sense, meas_seq, meas_pro, common_ext)
        # V_list = result[use_SMU]["V"]
        I_p_list = result[use_SMU]["I"]
        __postdata("I_p", I_p_list)
        if not is_d:
            V_list = result[use_SMU]["V"]
            __postdata("V", V_list)

    if is_d and is_p:
        I_p_p_list = [I_p_list[ind] - i for ind, i in enumerate(I_list)]
        if post_p.get("Il1"):
            Vr1_pos = MathLib.FINDLIN(V_list, spec_p["Vr1"], 0)
            Il1 = MathLib.AT(I_p_p_list, Vr1_pos)
            __postdata("Il1", [Il1])
        if post_p.get("Il2"):
            Vbr_Vx_pos = MathLib.FINDLIN(V_list, Vbr - spec_p["Vx"], 0)
            Il2 = MathLib.AT(I_p_p_list, Vbr_Vx_pos)
            __postdata("Il2", [Il2])

        __postdata("I_p_p", I_p_p_list)
        inst.write(use_SMU, ":sour:dig:ext13:pol neg")

    is_manual = DataManager().getgdata("Manual_Run")
    # print is_manual
    if is_manual:  # do reset if manual run
        IVFunc.commonsetup(is_rst={use_SMU: 1})


def calculate_Ip1(i_p_p):
    # get I_n+1/I_n
    i_delta2 = MathLib.DELTA_2(i_p_p)
    cnt = MathLib.scipy.ceil((len(i_p_p) - 1) * 0.05)
    cnt = int(cnt)
    # print cnt
    max_ind = []
    min_val = MathLib.MIN(i_delta2)
    for n in range(cnt):
        ind = MathLib.MAXPOS(i_delta2)
        max_ind.append(ind)
        i_delta2[ind] = min_val
    max_ind.sort()
    # print max_ind
    new_I_p_p = [i_p_p[i] for i in max_ind]
    new_I_p_p = MathLib.ABS(new_I_p_p)
    Ip1 = max(new_I_p_p)
    return Ip1


def key_convert(type_code, words):
    if type_code == "rng_mode":
        if words == "Limited Auto":
            return 2
        elif words == "Fixed":
            return 1
        elif words == "Auto":
            return 0
        elif words == "Best Fixed":
            return 1


def update_k(org, old_k, new_k):
    if new_k not in org:
        org[new_k] = org[old_k]
        del org[old_k]
    return org


def __postdata(name, val):
    DataManager().postarraydata(name, val)


#    print "########",name, val

def __log(level, msg):
    print(level, msg)


def reporterror(msg, code):
    __log("error", msg)
    return code
# if __name__ == "__main__":
#    import InstCom
#    InstCom.getinstconfig("online.rcf")
#    print InstCom.inst_dict
# import csv
# f = open(r"D:\MrBig_Project\209\IP1.csv")
# reader = csv.reader(f)
# line = []
# for l in reader:
#    line.append(l)
# i_list = [float(i) for i in line[1][1:]]
# print i_list
# print calculate_Ip1(i_list)
